package com.leo.business;

import java.util.List;

import javax.annotation.Resource;

import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.leo.dao.InterfaceDao;
import com.leo.entity.Score;
import com.leo.entity.StuUid;
import com.leo.entity.Student;
import com.leo.entity.User;
import com.leo.formbean.InterfaceForm;
import com.leo.util.JiaowuNetBug;
import com.leo.util.MemcachedUtil;
import com.leo.vo.NetBugResult;
import com.leo.vo.Result;

@Transactional
public class InterfaceBusinessImp implements InterfaceBusiness {

	@Resource
	private InterfaceDao interfaceDao;
	@Resource
	private JiaowuNetBug jiaowuNetBug;

	@Override
	@Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
	public Result getStuInfo(InterfaceForm interfaceForm){
		Result result = null;
		try {
			Object username = MemcachedUtil.getInstance().get(interfaceForm.getAccessToken());
			if(username == null) return Result.error("accessToken error");
			Student student = interfaceDao.findStudent(interfaceForm.getUid(), (String)username);
			result = Result.success(student);
		}catch (IndexOutOfBoundsException e) {
			result = Result.error("无此uid");
		}catch (Exception e) {
			result = Result.error("network error");
		}
		return result;
	}

	@Override
	public Result getScores(InterfaceForm interfaceForm){
		Result result = null;
		try {
			String username = (String) MemcachedUtil.getInstance().get(interfaceForm.getAccessToken());
			Student student = interfaceDao.findStudent(interfaceForm.getUid(), username);
			if(student.getScores().size() == 0 || Score.nowVersionTime() - student.getScores().get(0).getVersionTime() > 2 ){
				String stuID = student.getStuID(),
						password = student.getPassword();
				NetBugResult rs = jiaowuNetBug.getScore(stuID, password);
				if(!rs.getStatus().equals("1")){
					return Result.error(rs.getResult());
				}
				List<Score> scores = (List<Score>) rs.getResult();
				new Thread(new SaveScoresRunnable(scores,student)).start();
				student.getScores().addAll(scores);
				int versionTime = Score.nowVersionTime();
				result = Result.success(scores);
			}else{
				result = Result.success(student.getScores());
			}
		}catch (NullPointerException e) {
			result = Result.error("无此uid");
		}catch (Exception e) {
			result = Result.unknownError();
		}
		return result;
	}

	@Override
	/**
	 * 学生登录，会将学生信息本地化到本地数据库，并将学生账号关联到开发者账号，
	 * 返回一个openID作为关联的依据，开发者可以通过这个openID找到这个学生
	 * ps:同一个学生与不同开发者关联的openID是不同的，这决定了openID的不可共享的特性
	 * 保护的学生用户的信息安全
	 */
	public Result stuLogin(InterfaceForm interfaceForm) {
		// TODO Auto-generated method stub
		Result rs = null;
		//1、校验AccessToken
		MemcachedUtil mem = MemcachedUtil.getInstance();
		String dev = (String) mem.get(interfaceForm.getAccessToken());
		if(dev == null)
			return Result.error(("accessToken error or overdued"));
		
		//获取有效的学生信息
		//数据库内超过期限的学生信息视为无效，将从教务系统获取最新信息
		Student stu = interfaceDao.findStudent(interfaceForm.getUsername());
		if(stu == null || Student.nowVersionTime() - stu.getVersionTime() > 2){
			NetBugResult result = jiaowuNetBug.getInfo(interfaceForm.getUsername(), interfaceForm.getPassword());
			if(!"1".equals(result.getStatus() ) )
				return Result.error((result.getResult().toString()) );
			stu = (Student) result.getResult();
			stu.setVersionTime(Student.nowVersionTime());
			interfaceDao.updateOrSaveStudent(stu);
		}else{
			//校验密码
			if(!stu.getPassword().equals(interfaceForm.getPassword()))
				return Result.error("password incorrect");
		}
		
		//维护学生账号与开发者账号的关联吗，并返回关联关系的openID
		try{
			String hql = "select u from User u "
					+ "inner join u.stuUids uid "
					+ "inner join uid.student s where u.username=? and s.stuID=?";
			String uid = interfaceDao.findUid(interfaceForm.getUsername(), dev);
			return Result.success(uid);
		}catch(IndexOutOfBoundsException ex){
			//此处异常作为逻辑处理的一部分，表示该学生没有关注这个开发者。
			User user = interfaceDao.findUser(dev);;
			StuUid stuUid = new StuUid();
			stuUid.setUser(user);
			stuUid.setStudent(stu);
			interfaceDao.addUid(stuUid);
			rs = Result.success(stuUid.getOid());
		}catch (Exception e) {
			// TODO: handle exception
			//e.printStackTrace();
		}
		return rs;
	}

	@Override
	@Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
	public boolean validateCallback(InterfaceForm interfaceForm,String callback) {
		// TODO Auto-generated method stub
		try{
			Object username = MemcachedUtil.getInstance().get(interfaceForm.getAccessToken());
			if(username == null) return false;
			String appURL = interfaceDao.findUser((String)username).getAppURL();
			return callback.startsWith(appURL) || callback.startsWith("http://" + appURL);
		}catch (NullPointerException e) {
			// TODO: handle exception
			return false;
		}
	}
	
	private static class SaveScoresRunnable implements Runnable{

		static private final ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
		private List<Score> scores;
		private InterfaceDao interfaceDao;
		private Student student;
		private SaveScoresRunnable(){}
		SaveScoresRunnable(List<Score> scores, Student student){
			this.scores = scores;
			this.student = student;
		}
		@Override
		public void run() {
			interfaceDao = (InterfaceDao) ctx.getBean("interfaceDao");
			
			// TODO Auto-generated method stub
			int versionTime = Score.nowVersionTime();
			for(Score  score: scores){
				try{
					score.setStudent(student);
					score.setVersionTime(versionTime);
					interfaceDao.updateOrSaveScore(score);
				}catch (Exception e) {
					// TODO: handle exception
				}
			}
			interfaceDao.updateOrSaveStudent(student);
		}
	}
}
